﻿using System;
using System.Collections.Generic;
namespace Moonlite.ExtensionApi.ControlInterfaces
{
    public abstract class OutputStream
    {
        private Stack<string> messages;
        public event EventHandler Write;
        public event EventHandler Read;
        public event EventHandler Add;
        public event EventHandler Remove;
        public event EventHandler Clear;
        public abstract string Name { get; }
        public string Text
        {
            get
            {
                Stack<string> backup = new Stack<string>(messages);
                string text = "";
                for (int i = 0; i < messages.Count; i++)
                {
                    text += PopMessage() + Environment.NewLine;
                }
                messages = backup;
                return text;
            }
            set
            {
                if (value == null)
                {
                    throw new InvalidOperationException("value cannot be null.");
                }
                this.messages.Clear();
                if (value == "")
                {
                    return;
                }
                string[] messages = value.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = messages.Length - 1; i >= 0; i--)
                {
                    PushMessage(messages[i]);
                }
            }
        }
        protected virtual void OnWrite(EventArgs e)
        {
            if (Write != null)
            {
                Write(this, e);
            }
        }
        protected virtual void OnRead(EventArgs e)
        {
            if (Read != null)
            {
                Read(this, e);
            }
        }
        protected virtual void OnAdd(EventArgs e)
        {
            if (Add != null)
            {
                Add(this, e);
            }
        }
        protected virtual void OnRemove(EventArgs e)
        {
            if (Remove != null)
            {
                Remove(this, e);
            }
        }
        protected virtual void OnClear(EventArgs e)
        {
            if (Clear != null)
            {
                Clear(this, e);
            }
        }
        private void RaiseAddEvent()
        {
            OnAdd(EventArgs.Empty);
        }
        private void RaiseWriteEvent()
        {
            OnWrite(EventArgs.Empty);
        }
        private void RaiseRemoveEvent()
        {
            OnRemove(EventArgs.Empty);
        }
        private void RaiseReadEvent()
        {
            OnRead(EventArgs.Empty);
        }
        private void RaiseClearEvent()
        {
            OnClear(EventArgs.Empty);
        }
        public void PushMessage(string message)
        {
            RaiseWriteEvent();
            RaiseAddEvent();
            messages.Push(message);
        }
        public string PopMessage()
        {
            RaiseReadEvent();
            RaiseRemoveEvent();
            return messages.Pop();
        }
        public string PeekMessage()
        {
            RaiseReadEvent();
            return messages.Peek();
        }
        public void ClearMessages()
        {
            Text = "";
            RaiseClearEvent();
        }
        public override string ToString()
        {
            return Name;
        }
        public OutputStream()
            : this(new Stack<string>())
        {
        }
        public OutputStream(Stack<string> messages)
        {
            if (messages == null)
            {
                throw new ArgumentNullException("messages");
            }
            this.messages = messages;
        }
    }
}
